<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>状态切换动画</title>
  </head>

  <body>
    <div id="mountNode"></div>
    <script src="../build/g6.js"></script>
    <script>
      const nodes = [];
      const edges = [];
      const centerNode = {
        id: 'center',
        x: 500,
        y: 300,
        shape: 'center-node',
        size: 20,
      };
      nodes.push(centerNode);
      // 左侧添加 4 个节点
      for (var i = 0; i < 4; i++) {
        const id = 'left' + i;
        nodes.push({
          id,
          x: 250,
          y: (i + 1) * 100 + 50,
          shape: 'leaf-node',
        });
        edges.push({
          source: id,
          target: 'center',
          shape: 'can-running',
        });
      }

      for (var i = 0; i < 6; i++) {
        const id = 'right' + i;
        nodes.push({
          id,
          x: 750,
          y: i * 100 + 50,
          shape: 'leaf-node',
        });
        edges.push({
          source: 'center',
          target: id,
          shape: 'can-running',
        });
      }
      G6.registerNode(
        'leaf-node',
        {
          afterDraw(cfg, group) {
            group.addShape('circle', {
              attrs: {
                x: 0,
                y: 0,
                r: 5,
                fill: cfg.color || '#666',
              },
            });
          },
          getAnchorPoints() {
            return [
              [0, 0.5],
              [1, 0.5],
            ];
          },
        },
        'circle',
      );
      // 右侧添加 6 个节点
      G6.registerNode(
        'center-node',
        {
          afterDraw(cfg, group) {
            const r = cfg.size / 2;
            const back1 = group.addShape('circle', {
              zIndex: -3,
              attrs: {
                x: 0,
                y: 0,
                r: r + 10,
                fill: 'gray',
                opacity: 0.4,
              },
            });
            const back2 = group.addShape('circle', {
              zIndex: -2,
              attrs: {
                x: 0,
                y: 0,
                r: r + 20,
                fill: 'gray',
                // 为了显示清晰，随意设置了颜色
                opacity: 0.2,
              },
            });
            group.sort();
          },
          getAnchorPoints() {
            return [
              [0, 0.5],
              [1, 0.5],
            ];
          },
        },
        'circle',
      );
      // lineDash 的差值，可以在后面提供 util 方法自动计算
      const dashArray = [
        [0, 1],
        [0, 2],
        [1, 2],
        [0, 1, 1, 2],
        [0, 2, 1, 2],
        [1, 2, 1, 2],
        [2, 2, 1, 2],
        [3, 2, 1, 2],
        [4, 2, 1, 2],
      ];

      const lineDash = [4, 2, 1, 2];
      const interval = 9;
      G6.registerEdge(
        'can-running',
        {
          setState(name, value, item) {
            const shape = item.get('keyShape');
            if (name === 'running') {
              if (value) {
                const length = shape.getTotalLength(); // 后续 G 增加 totalLength 的接口
                let totalArray = [];
                for (var i = 0; i < length; i += interval) {
                  totalArray = totalArray.concat(lineDash);
                }
                let index = 0;
                shape.animate(
                  ratio => {
                    const cfg = {
                      lineDash: dashArray[index].concat(totalArray),
                    };
                    index = (index + 1) % interval;
                    return cfg;
                  },
                  {
                    repeat: true,
                    duration: 3000,
                  },
                );
              } else {
                shape.stopAnimate();
                shape.attr('lineDash', null);
              }
            }
          },
        },
        'cubic-horizontal',
      );
      const graph = new G6.Graph({
        container: 'mountNode',
        width: 1000,
        height: 600,
      });
      graph.data({
        nodes,
        edges,
      });
      graph.render();
      graph.on('node:mouseenter', ev => {
        const node = ev.item;
        const edges = node.getEdges();
        edges.forEach(edge => graph.setItemState(edge, 'running', true));
      });

      graph.on('node:mouseleave', ev => {
        const node = ev.item;
        const edges = node.getEdges();
        edges.forEach(edge => graph.setItemState(edge, 'running', false));
      });
    </script>
  </body>
</html>
